feat: add filesystem-backed SerDes stage - #648
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Addressed the remaining review findings and follow-up changes in c9d4390, 97f0e10, 6a813eb, 4164e46, fd92ee9, and 7f09c77:
Validation: targeted SDK tests (55 tests), examples test compilation, generator unit tests, all SAM/CloudFormation template-generation modes, Actionlint, Spotless, YAML parsing, and |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| if (ChainedInvokePayloadFrame.isFramed(inputPayload)) { | ||
| inputPayload = ChainedInvokePayloadFrame.decode(inputPayload); | ||
| serDes = config.getSerDes(); |
There was a problem hiding this comment.
Codex AI review
[P1] Do not let payload bytes select the persisted SerDes. This frame is only a prefix, so any caller able to supply it bypasses the configured input codec without callee opt-in or trusted provenance. This can bypass validation/decryption and make filesystem envelopes execute under the cross-execution INPUT rule. Carry this signal in trusted backend metadata or authenticate it with explicit callee opt-in; otherwise continue using getInputSerDes(). Add spoof and prefix-collision tests.
| + "'"); | ||
| } | ||
| try { | ||
| writePayload(payload, file); |
There was a problem hiding this comment.
Codex AI review
[P2] Avoid writing files for serialization results that will not be checkpointed. ChildContextOperation normalizes results before checking isVirtual or whether its parent already completed, so FLAT map/parallel branches and late branches publish UUID files whose envelopes are discarded. High-cardinality workflows therefore leak files and storage I/O. Move that skip decision before persisted serialization or provide a normalization-only path that runs the value codec without storage stages, with FLAT/early-completion file-count tests.
| } catch (IOException e) { | ||
| throw new RetryableSerDesException( | ||
| "Failed to store filesystem payload for entity '" + context.entityId() + "'", e); |
There was a problem hiding this comment.
Codex AI review
[P3] Do not classify every IOException as transient. Secure traversal failures for symlink components, non-directories, and permission errors also arrive as IOException; wrapping them as retryable makes RetrySerDesStage repeat permanently invalid paths for the full backoff. Convert structural/path-security failures to SerDesException and reserve RetryableSerDesException for genuinely transient storage failures. Apply the same distinction to the read catch and add retry-wrapper symlink tests.
Codex AI reviewFound one high-severity input-boundary issue and two filesystem lifecycle/error-handling defects. Cloud EFS behavior remains covered only by opt-in tests. Reviewed commit |
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Issue Link, if available
Closes #463.
Implements Approach A from ADR-005 and provides the SerDes context requested in #509.
Description
SerDeswiththen(SerDesStage), returning theSerDesinterface so fluent callers do not depend on the concrete pipeline implementation.SerDesvalue codec followed by zero or more reversibleString → StringSerDesStagecomponents. Serialization runs in declaration order and deserialization runs in reverse order.SerDesvalue codecs context-free and passSerDesContextexplicitly only toSerDesStageand nestedBinarySerDesStagecalls. Serialization-stage context exposes the root input object throughoriginalValue(); deserialization-stage context has a nulloriginalValue(). No SerDes-specific thread-local storage is used.CloudDurableTestRunnerandLocalDurableTestRunnerserialize initial invocation input with a separate context-free value codec. By default, they use the persisted SerDes when it is a plain value codec or the root value codec when it is composable;withInputSerDes(...)provides an explicit value-codec override. Persisted pipeline stages are not used to encode initial input.BinarySerDesStagefor reversiblebyte[] → byte[]transformations andComposableBinarySerDesStageto expose an ordered binary chain as one top-level string stage.StringBinaryCodecinterface. The processing-order builder usesstartWith(codec), zero or morethen(binaryStage)calls,endWith(codec), andbuild(). The outer stage adds a reserved versioned frame for reliable format recognition.RetryableSerDesException,RetrySerDesStage, andRetryBinarySerDesStage. The wrappers retry explicitly retryable failures using existing boundedRetryStrategyimplementations and pass the same stage context to every attempt.FileSystemSerDesStageto the core SDK as a reversibleSerDesStagefor filesystem-backed payload storage. The stage, storage/path configuration, and preview APIs live in the dedicatedsoftware.amazon.lambda.durable.serde.filesystemJava package without adding a Maven module.ALWAYS/OVERFLOWmodes, immutable content-hashed files, attempt-aware operation identities, and pass-through of unrecognized input.CREATE_NEWwrite. Publication does not use hard links or renames, so the implementation works on both EFS and S3 Files without overwriting data referenced by an earlier checkpoint.SerDesContext, includingoriginalValue().FileSystemSerDesStageto be followed by other stages that transform its inline or file-reference envelope. Filesystem overflow and preview-size checks apply at the filesystem stage boundary; later stages are responsible for their own size expansion.originalValue, binary stages, retry wrappers, filesystem stages, executor behavior, core SDK packaging, stage format recognition, structured previews, S3 Files compatibility, and independent test-runner input codecs.Demo/Screenshots
Not applicable. Configuration examples are included in the SerDes guide.
Checklist
Testing
Coverage includes:
SerDesplusSerDesStagepipeline creation, immutable appending, ordering, reverse processing, pass-through of unrecognized input, malformed recognized input, nulls, and failure metadata.SerDesStagecomponents can be appended after the root value codec and that fluent composition returns theSerDesinterface.Stageand filesystem-specific APIs live undersoftware.amazon.lambda.durable.serde.filesystem.SerDesContextpropagation through top-level stages, binary substages, executor-backed calls, and every retry attempt.originalValue()propagation to string stages, binary substages, retry wrappers, and filesystem preview callbacks; deserialization verifies that it is absent.Validated with:
mvn spotless:checkgit diff --checkCloud integration tests remain opt-in through
-Dtest.cloud.enabled=true.Examples
The SerDes guide, ADR, and design documentation include configuration examples.